#pragma once

const std::string& GetScriptFileById(uint32 scriptFileId);

int DoScriptFile(lua_State* L, const std::string& scriptFile);
int DoScriptFileById(lua_State* L, uint32 scriptFileId);

template <typename... Args>
void RunScriptFile(lua_State* L, const std::string& scriptFile, Args... args) {
	if (sLuaMgr.DoFile(L, scriptFile)) {
		LuaFunc(L, "main", true).Call<void>(std::forward<Args>(args)...);
	}
}
template <typename... Args>
void RunScriptFileById(lua_State* L, uint32 scriptFileId, Args... args) {
	const std::string& scriptFile = GetScriptFileById(scriptFileId);
	if (!scriptFile.empty() && sLuaMgr.DoFile(L, scriptFile)) {
		LuaFunc(L, "main", true).Call<void>(std::forward<Args>(args)...);
	}
}

template <typename... Args>
LuaFifoTopValues XRunScriptFile(lua_State* L, const std::string& scriptFile, Args... args) {
	if (sLuaMgr.DoFile(L, scriptFile)) {
		return LuaFunc(L, "main", true).XCall(std::forward<Args>(args)...);
	} else {
		return {};
	}
}
template <typename... Args>
LuaFifoTopValues XRunScriptFileById(lua_State* L, uint32 scriptFileId, Args... args) {
	const std::string& scriptFile = GetScriptFileById(scriptFileId);
	if (!scriptFile.empty() && sLuaMgr.DoFile(L, scriptFile)) {
		return LuaFunc(L, "main", true).XCall(std::forward<Args>(args)...);
	} else {
		return {};
	}
}

namespace lua {

	template<> struct pop<ObjGUID> {
		static ObjGUID invoke(lua_State *L) {
			return GetGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<const ObjGUID> {
		static ObjGUID invoke(lua_State *L) {
			return GetGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<const ObjGUID &> {
		static ObjGUID invoke(lua_State *L) {
			return GetGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<ObjGUID &&> {
		static ObjGUID invoke(lua_State *L) {
			return GetGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<const ObjGUID &&> {
		static ObjGUID invoke(lua_State *L) {
			return GetGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};

	template<> struct read<ObjGUID> {
		static ObjGUID invoke(lua_State *L, int index) {
			return GetGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<const ObjGUID> {
		static ObjGUID invoke(lua_State *L, int index) {
			return GetGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<const ObjGUID &> {
		static ObjGUID invoke(lua_State *L, int index) {
			return GetGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<ObjGUID &&> {
		static ObjGUID invoke(lua_State *L, int index) {
			return GetGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<const ObjGUID &&> {
		static ObjGUID invoke(lua_State *L, int index) {
			return GetGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};

	template<> struct push<ObjGUID> {
		static void invoke(lua_State *L, const ObjGUID &val) {
			lua_pushinteger(L, val.objGUID);
		}
	};
	template<> struct push<const ObjGUID> {
		static void invoke(lua_State *L, const ObjGUID &val) {
			lua_pushinteger(L, val.objGUID);
		}
	};
	template<> struct push<ObjGUID &> {
		static void invoke(lua_State *L, const ObjGUID &val) {
			lua_pushinteger(L, val.objGUID);
		}
	};
	template<> struct push<const ObjGUID &> {
		static void invoke(lua_State *L, const ObjGUID &val) {
			lua_pushinteger(L, val.objGUID);
		}
	};
	template<> struct push<ObjGUID &&> {
		static void invoke(lua_State *L, const ObjGUID &val) {
			lua_pushinteger(L, val.objGUID);
		}
	};
	template<> struct push<const ObjGUID &&> {
		static void invoke(lua_State *L, const ObjGUID &val) {
			lua_pushinteger(L, val.objGUID);
		}
	};

	template<> struct pop<InstGUID> {
		static InstGUID invoke(lua_State *L) {
			return GetInstGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<const InstGUID> {
		static InstGUID invoke(lua_State *L) {
			return GetInstGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<const InstGUID &> {
		static InstGUID invoke(lua_State *L) {
			return GetInstGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<InstGUID &&> {
		static InstGUID invoke(lua_State *L) {
			return GetInstGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};
	template<> struct pop<const InstGUID &&> {
		static InstGUID invoke(lua_State *L) {
			return GetInstGuidFromValue(lua::pop<uint64>::invoke(L));
		}
	};

	template<> struct read<InstGUID> {
		static InstGUID invoke(lua_State *L, int index) {
			return GetInstGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<const InstGUID> {
		static InstGUID invoke(lua_State *L, int index) {
			return GetInstGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<const InstGUID &> {
		static ObjGUID invoke(lua_State *L, int index) {
			return GetGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<InstGUID &&> {
		static InstGUID invoke(lua_State *L, int index) {
			return GetInstGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};
	template<> struct read<const InstGUID &&> {
		static InstGUID invoke(lua_State *L, int index) {
			return GetInstGuidFromValue(lua::read<uint64>::invoke(L, index));
		}
	};

	template<> struct push<InstGUID> {
		static void invoke(lua_State *L, const InstGUID &val) {
			lua_pushinteger(L, val.instGUID);
		}
	};
	template<> struct push<const InstGUID> {
		static void invoke(lua_State *L, const InstGUID &val) {
			lua_pushinteger(L, val.instGUID);
		}
	};
	template<> struct push<InstGUID &> {
		static void invoke(lua_State *L, const InstGUID &val) {
			lua_pushinteger(L, val.instGUID);
		}
	};
	template<> struct push<const InstGUID &> {
		static void invoke(lua_State *L, const InstGUID &val) {
			lua_pushinteger(L, val.instGUID);
		}
	};
	template<> struct push<InstGUID &&> {
		static void invoke(lua_State *L, const InstGUID &val) {
			lua_pushinteger(L, val.instGUID);
		}
	};
	template<> struct push<const InstGUID &&> {
		static void invoke(lua_State *L, const InstGUID &val) {
			lua_pushinteger(L, val.instGUID);
		}
	};

}
